{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using device: cuda\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 物理参数\n",
    "alpha = 0.01  # 热扩散系数\n",
    "\n",
    "# 选择设备（CUDA or CPU）\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "#device = \"cpu\"\n",
    "print(\"Using device:\", device)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义 PINN 网络\n",
    "class PINN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(PINN, self).__init__()\n",
    "        self.net = nn.Sequential(\n",
    "            nn.Linear(2, 32), nn.Tanh(),\n",
    "            nn.Linear(32, 32), nn.Tanh(),\n",
    "            nn.Linear(32, 32), nn.Tanh(),\n",
    "            nn.Linear(32, 1)\n",
    "        )\n",
    "\n",
    "    def forward(self, x, t):\n",
    "        xt = torch.cat((x, t), dim=1)  # 连接 x 和 t 作为输入\n",
    "        return self.net(xt)\n",
    "\n",
    "# 计算物理损失\n",
    "def pde_loss(model, x, t):\n",
    "    x.requires_grad = True\n",
    "    t.requires_grad = True\n",
    "    u = model(x, t)\n",
    "\n",
    "    # 计算一阶导数 du/dt\n",
    "    u_t = torch.autograd.grad(u, t, grad_outputs=torch.ones_like(u), create_graph=True)[0]\n",
    "\n",
    "    # 计算二阶导数 d²u/dx²\n",
    "    u_x = torch.autograd.grad(u, x, grad_outputs=torch.ones_like(u), create_graph=True)[0]\n",
    "    u_xx = torch.autograd.grad(u_x, x, grad_outputs=torch.ones_like(u_x), create_graph=True)[0]\n",
    "\n",
    "    # 物理方程残差\n",
    "    return torch.mean((u_t - alpha * u_xx) ** 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0, Loss: 0.5061171054840088\n",
      "Epoch 500, Loss: 0.00015454912499990314\n",
      "Epoch 1000, Loss: 3.907850623363629e-05\n",
      "Epoch 1500, Loss: 1.5674271708121523e-05\n",
      "Epoch 2000, Loss: 7.786512469465379e-06\n",
      "Epoch 2500, Loss: 5.0097219173039775e-06\n",
      "Epoch 3000, Loss: 3.367622866790043e-06\n",
      "Epoch 3500, Loss: 3.612108685047133e-06\n",
      "Epoch 4000, Loss: 2.243032895421493e-06\n",
      "Epoch 4500, Loss: 2.097451442750753e-06\n"
     ]
    }
   ],
   "source": [
    "# 生成训练数据\n",
    "N_f, N_b, N_i = 10000, 100, 100  # PDE 点、边界点、初始点\n",
    "\n",
    "# 随机生成物理方程点 (x, t)\n",
    "x_f = torch.rand((N_f, 1), dtype=torch.float32, requires_grad=True, device=device)\n",
    "t_f = torch.rand((N_f, 1), dtype=torch.float32, requires_grad=True, device=device)\n",
    "\n",
    "# 边界条件数据 (u(0,t) = u(1,t) = 0)\n",
    "x_b = torch.cat([torch.zeros((N_b, 1)), torch.ones((N_b, 1))], dim=0).to(device)\n",
    "t_b = torch.rand((2 * N_b, 1), device=device)\n",
    "u_b = torch.zeros((2 * N_b, 1), device=device)\n",
    "\n",
    "# 初始条件数据 (u(x,0) = sin(pi*x))\n",
    "x_i = torch.rand((N_i, 1), device=device)\n",
    "t_i = torch.zeros((N_i, 1), device=device)\n",
    "u_i = torch.sin(np.pi * x_i).to(device)\n",
    "\n",
    "# 初始化模型并移动到 CUDA\n",
    "model = PINN().to(device)\n",
    "optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "# 训练\n",
    "epochs = 5000\n",
    "for epoch in range(epochs):\n",
    "    optimizer.zero_grad()\n",
    "\n",
    "    # 计算损失\n",
    "    loss_pde = pde_loss(model, x_f, t_f)\n",
    "    loss_bc = torch.mean((model(x_b, t_b) - u_b) ** 2)\n",
    "    loss_ic = torch.mean((model(x_i, t_i) - u_i) ** 2)\n",
    "    loss = loss_pde + loss_bc + loss_ic\n",
    "\n",
    "    # 反向传播和优化\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "\n",
    "    # 打印训练进度\n",
    "    if epoch % 500 == 0:\n",
    "        print(f\"Epoch {epoch}, Loss: {loss.item()}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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TzzheBkBP6MBCsu+//57SVKDBg2OuWytWrV0++2365133tF7771nKf8bbrhBTZs21S233BJ22XJyclReXq6LLrpI77zzjnbv3l3lss8995wGDhyozMxMLV68WHl5efr111919tln6+OPPw5720c6/fTTNW/ePEnS7bffXvmI9cjIzeGuueYa3XrrrTrvvPP02muv6e6779bbb7+tbt26qbi4OGjZrVu36vLLL9cVV1yh1157Tf369dPEiRP17LPPHrVcy5cvV/Xq1XXBBRdUlmn27NmSpG+//VbdunXT119/rZkzZ+rll19W27ZtNXz4cD344IM2j4h1Z5xxhho3bqyPPvrI0vLl5eUqLS0N+Zg1xp999ln16dNHmZmZWrBggZ5//nnVrVtXffv2DWqEbtmyRfXq1dP999+vt99+W7NmzVJKSoq6du1a2UUkknN8rDIfbvTo0Xr44Yc1bNgw/eMf/9DFF1+siy66SL/++qul42Lmu+++0wUXXKC8vDy9/fbbGjdunJ5//nkNGDCgcpk77rhDl1xyiSQFdQ9o3LixaZ6//PKLunXrpnfffVd33323XnvtNfXu3Vs33XSTrrvuupDlZ82apfz8fM2YMUOLFi3S3r17dcEFF2jXrl1HLfumTZu0bt06nXPOOUHp7777rqRDTzq8UL16dfXu3VsbN24Mulncv3+/Fi9erDPOOEPt2rXTVVddpT179uiFF14wzefss8/WJ598op07d7pUcsAHDOAI8+bNMyQZK1asMA4ePGjs2bPHeOONN4wGDRoYtWrVMrZu3WoYhmG8//77hiTjhRdeCFl35cqVRklJiXH88ccbnTt3NsrLyw3DMIyePXsap5xyStD2srOzjf79+xuGYRhPP/20Icl4/fXXq9yGmfLycuPqq682kpKSDElGIBAw2rRpY4wfP97YuHFj5XJlZWVGkyZNjPbt2xtlZWWV6Xv27DEaNmxodOvWLWRfDl8/OzvbuPLKK0O237NnT6Nnz56V/1+5cqUhyZg3b17IspMnTzYOv/S++eYbQ5IxduzYoOU+++wzQ5Jx2223BW1HkvHZZ58FLdu2bVujb9++VR2eSjVq1DAt/6WXXmqkpaUZBQUFQen9+vUzMjIyjJ07dx4z7wrXXnutUVXVYuV8du3a1ahevfpRt7Fx40ZD0jE/Fedu7969Rt26dY0BAwYE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F1+sn376SQ8++GDIzAAnnHCCqlevrkWLFqlNmzaqWbOmmjRpYvpo+eSTT9af//xnPfbYY0pKSlK/fv30448/6o477lDz5s0dbYy1b99eH3zwgV5//XU1btxYtWrV0sknn6zJkyfrjTfe0DnnnKM777xTdevW1aJFi/Tmm2/qwQcfVO3atY+a708//aSVK1dK+m8joSL607Jly5BI+nfffacVK1aovLxc27dv12effaa8vDzt3r1bCxcutPQdCUfNmjX12GOP6corr9SOHTt0ySWXqGHDhvrll1+0du1a/fLLL5ozZ46kQ2/DmT9/vlq3bq0OHTpo9erVeuihh0Ki0+GcY7N9P1LF/LBt2rTRFVdcoRkzZqhatWrq3bu3vvrqKz388MPKzMwMWueCCy5Q3bp1NXLkSE2dOlUpKSmaP39+yJu/unXrpjp16mjMmDGaPHmyqlWrpkWLFplO0F4x/+oDDzygfv36KTk5WR06dKhsoB9u/PjxWrhwofr376+pU6cqOztbb775pmbPnq1rrrlGJ5100lGPhVVdu3ZV9erVtWLFCl144YVBf1u4cKHOP/989evXT1dddZX69eunOnXqqKioSK+//roWL16s1atXq0WLFqpVq5amTJmiG2+8UeXl5RoyZIjq1KmjdevW6b777lN2drauv/76kO3//PPPWrFihQzD0J49e/TVV19p4cKFWrt2rcaPH6/Ro0dLkt566y1t2bJFDzzwQNAUZxXatWunxx9/XHl5efrjH/9Ymb5ixQrVq1cvbue+BUx5OAAKPnWskaIVjjUK/kiXXXaZIemoo+APt379eiM5OdnSKPgVK1YY1157rdGxY0ejbt26RnJystGgQQPj/PPPN5YuXRqy/Kuvvmp07drVSE9PN2rUqGH06tXL+OSTT0yPw+EjicvLy40HH3zQOP7444309HSjc+fOxnvvvRcyCt4wDGPx4sVG69atjWrVqhmSjMmTJxuGYT5yuayszHjggQeMk046yahWrZpRv35944orrqgcGV3BbBYBwzCMK6+8MmT0rpkvv/zS6N69u5GRkWFICirzunXrjAEDBhi1a9c2UlNTjY4dO1oe4V1xrMw+h4+aPnIkeEpKilGvXj0jJyfHuO2224wff/zR0vYqRlU/9NBDpn9/6KGHTEeBf/jhh0b//v2NunXrGtWqVTOaNm1q9O/fP+j79euvvxojR440GjZsaGRkZBhnnXWWsWzZsrDOsZljjYKfNGlS5bIlJSXGjTfeaDRs2NBIT083zjzzTGP58uWmszB8/vnnRrdu3YwaNWoYTZs2NSZPnmw888wzIfv/6aefGjk5OUZGRobRoEEDY9SoUcYXX3wRMpK/pKTEGDVqlNGgQQMjEAgE5WO2/Z9++sm47LLLjHr16hnVqlUzTj75ZOOhhx4KmmXiaOfrWMetwtChQ422bdua/m3//v3GzJkzjZycHCMzM9NISUkxmjRpYlx00UXGm2++GbL8888/b5x11llGrVq1jJSUFKNFixbGNddcUznDx5Hlq/gkJSUZmZmZRvv27Y0///nPxvLly4OWHTRokJGammps27atyv249NJLjZSUlMptlZeXG9nZ2cZf/vKXYx4DIJ4EDCOMIacAAM+0bNlSZ599tm/eG++mVatW6YwzztCKFStM3ygUq/71r3+pT58++vrrryu7GgCJgD6gAADf69y5swYPHqy7777b66I46p577tFVV11F4xMJhwYoACAmPPLIIzrjjDO0Z88er4viiF9//VU9e/bUvffe63VRANfxCB4AAACu8jQC+tFHH2nAgAFq0qSJAoGAXn311WOu8+GHH6pTp05KT0/X8ccfryeeeCL6BQUAAIBjPG2A7t27Vx07dtTjjz9uafmNGzfqggsuUI8ePbRmzRrddtttuv766/XSSy9FuaQAAABwim8ewQcCAb3yyisaNGhQlcvceuuteu2114LeWzxmzBitXbvW1XdVAwAAIHIxNRH98uXL1adPn6C0vn37Ki8vTwcPHjR9h29JSUnQqxPLy8u1Y8cO1atXr/LtIAAAwN+M/3sRQJMmTZSU5P4D3N9//10HDhyIWv6pqamVr9dNBDHVAN26dWvIe3qzsrJUWlqq4uLioHcEV5g2bZqmTJniVhEBAEAUFRYWhryZLNp+//13tWrVSlu3bo3aNho1aqSNGzcmTCM0phqgkkKilhU9CKqKZk6cOFG5ubmV/9+1a5datGihdEmHr1HHZN26Jmn1TdKsrmu2nNP5WV3X7MWKyZkmiWYZHrmy2QbM8jLbqNW0Wha3UdNifmbLmW3D7LXwZuvWMElLrW6xMGYrH2exMGbrWi2gWZpZxRf6Ckbz5czSkk3SzKodq2lmzLZxpDKLeZXaSDPbxu8W08yi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AABAlerUqRM0CMkwDO3Zs0cZGRl69tlnI8qTBigAAIAVCToR/V//+tegBmhSUpIaNGigrl27qk6dOhHlSQMUAAAAVTr33HPVvHlz06mYCgoK1KJFi7DzpIcJAACAFWVR/PhYq1at9Msvv4Skb9++Xa1atYooTyKgPpRQdwVWJ3+3M/DJswPK5WXvxEX7+LkxOb3VbVjdV6eXixPxMDDS4j7E4q7GYpkRzDDM54n67bfflJ6eHlGeCVZLAQAARCjBRsHn5uZKkgKBgO68805lZGRU/q2srEyfffaZTj311IjypgEKAABgRYINQlqzZo2kQxHQdevWKTU1tfJvqamp6tixo2666aaI8qYBCgAAgBDvv/++JGnEiBF69NFHlZmZ6VjeNEABAACsSLBH8BXmzZvneJ40QF1ER2yHxfVoLTuDTdx4U5Ofqg4rZXF6cJEZNwY12eGjc+bG4EM3RFq+uK67EK9WrlypF154QQUFBTpw4EDQ315++eWw8+MyAAAAsKJc0ZmCyad9QCv8/e9/V/fu3bV+/Xq98sorOnjwoNavX6/33ntPtWvXjihPGqAAAACo0n333ae//vWveuONN5SamqpHH31U33zzjQYPHhzRJPQSDVAAAABryqP48bEffvhB/fv3lySlpaVp7969CgQCGj9+vJ566qmI8vRRpyDELKu3MXF9u+P3S8mN8vl5G37vn2nGq++U2Xb9/EIB+L2rLGJf3bp1tWfPHklS06ZN9dVXX6l9+/bauXOn9u3bF1Ge1AwAAABWJOgo+B49eig/P1/t27fX4MGDdcMNN+i9995Tfn6+evXqFVGeNEABAABQpccff1y///67JGnixImqVq2aPv74Y1100UW64447IsqTBigAAIAVCfYmJEkqLS3V66+/rr59+0qSkpKSdMstt+iWW26xlW9c98oDAABwTDSmYIrWY32HpKSk6JprrlFJSYmz+TqaG1xFx3MTdg6K2bq+ukVz+nL10yAXv1RFVsvh9wFMVjn90gIX2LnGza7naF/jPq+ofV48+ETXrl21Zs0aZWdnO5anX2p9AAAAf0vQQUhjx47VjTfeqE2bNqlTp06qUaNG0N87dOgQdp40QAEAAFClIUOGSJKuv/76yrRAICDDMBQIBFRWFn4LOuwGaEFBgZo3b65AIBCUbhiGCgsLI54RHwAAwNcScBCSJG3c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",
      "text/plain": [
       "<Figure size 800x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 预测结果\n",
    "x_test = np.linspace(0, 1, 100)\n",
    "t_test = np.linspace(0, 1, 100)\n",
    "X, T = np.meshgrid(x_test, t_test)\n",
    "X_test = torch.tensor(X.flatten(), dtype=torch.float32, device=device).view(-1, 1)\n",
    "T_test = torch.tensor(T.flatten(), dtype=torch.float32, device=device).view(-1, 1)\n",
    "\n",
    "with torch.no_grad():\n",
    "    U_pred = model(X_test, T_test).cpu().numpy().reshape(100, 100)  # 将结果移回 CPU 以便绘图\n",
    "\n",
    "# 绘制结果\n",
    "plt.figure(figsize=(8, 6))\n",
    "plt.imshow(U_pred, extent=[0, 1, 0, 1], origin=\"lower\", aspect=\"auto\", cmap=\"hot\")\n",
    "plt.colorbar(label=\"Temperature\")\n",
    "plt.xlabel(\"x\")\n",
    "plt.ylabel(\"t\")\n",
    "plt.title(\"PINN Solution to 1D Heat Equation (CUDA)\")\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
